/*
采用 gethostbyname 和 getservbyname 传入主机名和服务名实现的 TCP 时间获取客户端。
**/

#include <define.h>
#include <error.h>
#include <wrapfunc.h>
#include <sockfunc.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stddef.h>
#include <string.h>


int
main(int argc, char **argv) {
    if (argc != 3)
        error_quit("usage: %s host servname", argv[0]);
    const char *host = argv[1]; // /etc/hosts /etc/resolv.conf
    const char *servname = argv[2]; // 服务名 /etc/services daytime

    struct in_addr addr;
    struct in_addr *addrtmp[2];
    struct in_addr **addrlist;

    if (inet_aton(host, &addr) == 0) {
        struct hostent *entry = gethostbyname(host);
        if (entry == NULL)
            error_quit("fail to gethostbyname host:%s error:%s", host, hstrerror(h_errno));
        addrlist = (struct in_addr **)entry->h_addr_list;
    } else {
       addrtmp[0] = &addr;
       addrtmp[1] = NULL;
       addrlist = (struct in_addr **)&addrtmp;
    }

    struct servent *sentry = getservbyname(servname, "tcp");
    if (sentry == NULL)
        error_quit("fail to getservbyname");

    int fd;
    for (struct in_addr **ptr=addrlist; *ptr; ptr++) {
        struct sockaddr_in servaddr;
        memset(&servaddr, 0, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = sentry->s_port;
        memcpy(&servaddr.sin_addr, *ptr, sizeof(servaddr.sin_addr));
        
        error_msg("try connect to %s", sock_ntop((struct sockaddr*)&servaddr, sizeof(servaddr)));
        fd = Socket(AF_INET, SOCK_STREAM, 0);
        if (connect(fd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) {
            Close(fd);
            fd = -1;
            continue;
        } else {
            break;
        }
    }

    if (fd < 0)
        error_quit("fail to connect to host");
    
    ssize_t n;
    char buf[MAX_LINE];
    while ((n=Read(fd, buf, sizeof(buf)-1)) > 0) {
        buf[n] = 0;
        error_msg("daytime from server:%s", buf);
    }

    Close(fd);
    return 0;
}

